/*
 * @Author: shanghongyun 2879455630@qq.com
 * @Date: 2025-05-30 15:38:07
 * @LastEditors: shanghongyun 2879455630@qq.com
 * @LastEditTime: 2025-07-23 16:31:03
 * @FilePath: \A05\Drive\display.c
 * @Description: display 显示
 */
#include "display.h"
#include "charger.h"

bat_display_t display_L;
bat_display_t display_R;

/*数码管段码 共阴数码管0~9*/
uint8_t Segment_code[] = {DISPLAY_0,DISPLAY_1,DISPLAY_2,DISPLAY_3,DISPLAY_4,
                            DISPLAY_5,DISPLAY_6,DISPLAY_7,DISPLAY_8,DISPLAY_9};

uint8_t display_data[14];

#define DELAY       Delay_us(1)


/**
 * @description: 延时ms
 * @param {uint32_t} ms
 * @return {*}
 */
static void delay_ms(uint32_t ms){
    #define _1ms_pulse          (12000)            /*48Mhz 1ms需要执行的机器周期*/
    uint32_t delay = ms * _1ms_pulse;
    while(delay--) ; 
}

static void Delay_us(uint32_t us){
    uint32_t time = us * 2;
    while(time--) ;
}



/**
 * @description: 显示元素变量获取
 * @param {*}
 * @return {*}
 */
static void Get_display_variable(bat_display_t * pBat_display , Battery_t * pBat){
    pBat_display->voltage_bat     = pBat->voltage / 10     ;
    pBat_display->current_bat     = pBat->current / 10     ;
    pBat_display->capacity_bat    = pBat->capacity / 10    ;
    pBat_display->charge_time_bat = pBat->charge_time      ;
    pBat_display->stage_bat       = pBat->vol_stage.stage;
}



/**
 * @description: 转换为数码管显示段码
 * @param {display_Num_t} *pNum
 * @param {uint16_t} data
 * @return {*}
 */
static void Digit_turn(display_Num_t *pNum , uint16_t data){
    uint8_t ones , tens , hundreds;
    ones = data % 10;
    tens = data / 10 % 10;
    hundreds = data / 100 % 10;
    pNum->ones = Segment_code[ones];
    pNum->tens = Segment_code[tens];
    pNum->hundreds = Segment_code[hundreds];
}


static void I2C_start(void){
    DISPLAY_SDA_HIGH;
    DELAY;
    DISPLAY_SCL_HIGH;
    DELAY;
    DISPLAY_SDA_LOW;
    DELAY;
    DISPLAY_SCL_LOW;
}


static void I2C_stop(void){
    DISPLAY_SDA_LOW;
    DELAY;
    DISPLAY_SCL_HIGH;
    DELAY;
    DISPLAY_SDA_HIGH;
    DELAY;
}


static void Send_Byte(uint8_t byte){
    for(int i = 0; i < 8; i++){
        DISPLAY_SCL_LOW;
        DELAY;
        if(byte & (0x01 << i)){
            DISPLAY_SDA_HIGH;
        }
        else{
            DISPLAY_SDA_LOW;
        }
        DELAY;
        DISPLAY_SCL_HIGH;
        DELAY;
        DELAY;
    }
    DISPLAY_SCL_LOW;
    DELAY;
}


static void AIP1640_display(uint8_t * data){
    __disable_irq();

    I2C_start();
    Send_Byte(0x40);
    I2C_stop();

    I2C_start();
    Send_Byte(0xc0);
    for(uint8_t i = 0 ; i < 14 ; i++){
        Send_Byte(data[i]);
    }
    I2C_stop();

    I2C_start();
    Send_Byte(0x8F);
    I2C_stop();

    __enable_irq();
}


static void display_clear_all(void){
    for(uint8_t i = 0; i < 14; i++){
        display_data[i] = 0x00;
    }
}



/**
 * @description: 清除单个显示槽
 * @param {display_Num_t *} pNum
 * @return {*}
 */
static void display_clear_one(display_Num_t * pNum){
    pNum->hundreds = 0x00;
    pNum->tens = 0x00;
    pNum->ones = 0x00;
}


/**
 * @description: 显示故障
 * @param {uint8_t} bat_index
 * @return {*}
 */
static void display_show_error(bat_display_t * pBat_display , Battery_t * pBat){
    if(pBat->err.Byte & 0x40){
        pBat_display->cur_bat.hundreds = 0x00;
        pBat_display->cur_bat.tens = DISPLAY_ERR_E;
        pBat_display->cur_bat.ones = DISPLAY_ERR_0;
    }
    else if(pBat->err.Byte & 0x08){
        pBat_display->cur_bat.hundreds = 0x00;
        pBat_display->cur_bat.tens = DISPLAY_ERR_E;
        pBat_display->cur_bat.ones = DISPLAY_ERR_F;
    }
    else{
        pBat_display->cur_bat.hundreds = 0x00;
        pBat_display->cur_bat.tens = DISPLAY_ERR_E;
        pBat_display->cur_bat.ones = DISPLAY_ERR_E;
    }
}


void Battery_L_IDLE_PAGE_func(void);
void Battery_L_CHARGE_PAGE_func(void);
void Battery_L_SET_CURRENT_func(void);
void Battery_L_ERROR_PAGE_func(void);
void Battery_L_CHARGE_EN_PAGE_func(void);

void Battery_R_IDLE_PAGE_func(void);
void Battery_R_CHARGE_PAGE_func(void);
void Battery_R_SET_CURRENT_func(void);
void Battery_R_ERROR_PAGE_func(void);
void Battery_R_CHARGE_EN_PAGE_func(void);


display_Type display_L_page = {
    .page = IDLE_PAGE,
    .display_func = {Battery_L_IDLE_PAGE_func, Battery_L_CHARGE_PAGE_func, Battery_L_SET_CURRENT_func, 
                        Battery_L_ERROR_PAGE_func,Battery_L_CHARGE_EN_PAGE_func}
};

display_Type display_R_page = {
    .page = IDLE_PAGE,
    .display_func = {Battery_R_IDLE_PAGE_func, Battery_R_CHARGE_PAGE_func, Battery_R_SET_CURRENT_func, 
                        Battery_R_ERROR_PAGE_func,Battery_R_CHARGE_EN_PAGE_func}
};

#define OFF_TIME    4
#define ON_TIME     3
#define Refresh_Time    8
#define BREATH_TIME     2

static void Reset_flash_time(display_Type * pDisplay){
    pDisplay->flash_time = 0;
}

static void bat_Reset_flash_time(Battery_t * pBat){
    pBat->screen_refresh_time = 0;
    pBat->breath_stage = pBat->vol_stage.stage;
    pBat->breath_time = 0;
}

void Clear_flash_time(void){
    // charger.battery_L.screen_refresh_time = 0;
    // charger.battery_R.screen_refresh_time = 0;
    charger.battery_L.fast_show = 1;
    charger.battery_R.fast_show = 1;

}



void Battery_L_IDLE_PAGE_func(void){
    Digit_turn(&display_L.vol_bat , 0);
    Digit_turn(&display_L.cur_bat , 0);
    Digit_turn(&display_L.cap_bat , 0);
    Digit_turn(&display_L.c_time_bat , 0);

    display_data[0] = display_L.vol_bat.hundreds | 0x80;
    display_data[1] = display_L.vol_bat.tens           ;
    display_data[2] = display_L.vol_bat.ones     | 0x80;

    display_data[6] = display_L.cur_bat.hundreds | 0x80;
    display_data[7] = display_L.cur_bat.tens           ;
    display_data[8] = display_L.cur_bat.ones     | 0x80;

    display_data[12] = 0xF0 | (~(0xFF << 0));
}

void Battery_L_CHARGE_PAGE_func(void){
    Battery_t * L_Bat = &charger.battery_L;

    if(L_Bat->fast_show){
        L_Bat->fast_show = 0;
        L_Bat->screen_refresh_time = Refresh_Time;
        L_Bat->breath_time = BREATH_TIME;
    }

    if(++L_Bat->breath_time > BREATH_TIME){
        L_Bat->breath_time = 0;
        if(++L_Bat->breath_stage > 4){
            L_Bat->breath_stage = L_Bat->vol_stage.stage;
        }
        display_data[12] = 0xF0 | (~(0xFF << L_Bat->breath_stage));
    }
    
    if(++L_Bat->screen_refresh_time > Refresh_Time){
        L_Bat->screen_refresh_time = 0;
        Digit_turn(&display_L.vol_bat , (L_Bat->voltage / 10));
        #if (SHOW_CURRENT_MODE == SHOW_REALTIME_CURRENT)
            Digit_turn(&display_L.cur_bat , (L_Bat->current / 10));
        #elif (SHOW_CURRENT_MODE == SHOW_SET_CURRENT)
            Digit_turn(&display_L.cur_bat , (L_Bat->current_set / 10));
        #endif
        Digit_turn(&display_L.cap_bat , (L_Bat->capacity / 10));
        Digit_turn(&display_L.c_time_bat , L_Bat->charge_time);

        display_data[0] = display_L.vol_bat.hundreds | 0x80;
        display_data[1] = display_L.vol_bat.tens           ;
        display_data[2] = display_L.vol_bat.ones     | 0x80;

        display_data[6] = display_L.cur_bat.hundreds | 0x80;
        display_data[7] = display_L.cur_bat.tens           ;
        display_data[8] = display_L.cur_bat.ones     | 0x80;
    }
}


void Battery_L_SET_CURRENT_func(void){
    Battery_t * L_Bat = &charger.battery_L;
    
    L_Bat->screen_refresh_time++;
    if(L_Bat->screen_refresh_time < ON_TIME){ 
        Digit_turn(&display_L.vol_bat , (L_Bat->voltage / 10));
        Digit_turn(&display_L.cur_bat , (L_Bat->current_set / 10));
        Digit_turn(&display_L.cap_bat , (L_Bat->capacity / 10));
        Digit_turn(&display_L.c_time_bat , L_Bat->charge_time);

        display_data[0] = display_L.vol_bat.hundreds | 0x80;
        display_data[1] = display_L.vol_bat.tens           ;
        display_data[2] = display_L.vol_bat.ones     | 0x80;

        display_data[6] = display_L.cur_bat.hundreds | 0x80;
        display_data[7] = display_L.cur_bat.tens           ;
        display_data[8] = display_L.cur_bat.ones     | 0x80;
    }
    else if(L_Bat->screen_refresh_time < OFF_TIME){
        display_clear_one(&display_L.cur_bat);

        display_data[0] = display_L.vol_bat.hundreds | 0x80;
        display_data[1] = display_L.vol_bat.tens           ;
        display_data[2] = display_L.vol_bat.ones     | 0x80;

        display_data[6] = display_L.cur_bat.hundreds ;
        display_data[7] = display_L.cur_bat.tens     ;
        display_data[8] = display_L.cur_bat.ones;
    }
    
    else{
        L_Bat->screen_refresh_time = 0;
    }

    display_data[12] = 0xF0 | (~(0xFF << L_Bat->vol_stage.stage));
}


void Battery_L_ERROR_PAGE_func(void){
    Battery_t * L_Bat = &charger.battery_L;

    L_Bat->screen_refresh_time++;
    if(L_Bat->screen_refresh_time < ON_TIME){ 
        display_clear_one(&display_L.vol_bat);
        display_show_error(&display_L , L_Bat);
    }
    else if(L_Bat->screen_refresh_time < OFF_TIME){
        display_clear_one(&display_L.cur_bat);
        display_clear_one(&display_L.vol_bat);
    }
    
    else{
        L_Bat->screen_refresh_time = 0;
    }

    display_data[0] = display_L.vol_bat.hundreds ;//| 0x80;
    display_data[1] = display_L.vol_bat.tens           ;
    display_data[2] = display_L.vol_bat.ones     ;//| 0x80;

    display_data[6] = display_L.cur_bat.hundreds ;//| 0x80;
    display_data[7] = display_L.cur_bat.tens           ;
    display_data[8] = display_L.cur_bat.ones     ;//| 0x80;

    display_data[12] = 0xF0 | (~(0xFF << 0));
}


void Battery_L_CHARGE_EN_PAGE_func(void){
    Battery_t * L_Bat = &charger.battery_L;

    if(++L_Bat->screen_refresh_time > Refresh_Time){
        L_Bat->screen_refresh_time = 0;
        Digit_turn(&display_L.vol_bat , (L_Bat->voltage / 10));
        Digit_turn(&display_L.cur_bat , 0);
        Digit_turn(&display_L.cap_bat , (L_Bat->capacity / 10));
        Digit_turn(&display_L.c_time_bat , L_Bat->charge_time);

        display_data[0] = display_L.vol_bat.hundreds | 0x80;
        display_data[1] = display_L.vol_bat.tens           ;
        display_data[2] = display_L.vol_bat.ones     | 0x80;

        display_data[6] = display_L.cur_bat.hundreds | 0x80;
        display_data[7] = display_L.cur_bat.tens           ;
        display_data[8] = display_L.cur_bat.ones     | 0x80;

        display_data[12] = 0xF0 | (~(0xFF << L_Bat->vol_stage.stage));
    }
}



void Battery_R_IDLE_PAGE_func(void){
    Digit_turn(&display_R.vol_bat , 0);
    Digit_turn(&display_R.cur_bat , 0);
    Digit_turn(&display_R.cap_bat , 0);
    Digit_turn(&display_R.c_time_bat , 0);

    uint8_t slow_charge = charger.flash_charger ? 0x00 : 0x80;
    uint8_t flash_charge = charger.flash_charger ? 0x80 : 0x00;

    display_data[3] = display_R.vol_bat.hundreds | slow_charge;
    display_data[4] = display_R.vol_bat.tens     | 0x80;
    display_data[5] = display_R.vol_bat.ones     | 0x80;

    display_data[9] = display_R.cur_bat.hundreds | flash_charge;
    display_data[10] = display_R.cur_bat.tens     | 0x80;
    display_data[11] = display_R.cur_bat.ones     | 0x80;

    display_data[13] = 0xF0 | (~(0xFF << 0));
}


void Battery_R_CHARGE_PAGE_func(void){
    Battery_t * R_Bat = &charger.battery_R;

    if(R_Bat->fast_show){
        R_Bat->fast_show = 0;
        R_Bat->screen_refresh_time = Refresh_Time;
        R_Bat->breath_time = BREATH_TIME;
    }

    if(++R_Bat->breath_time > BREATH_TIME){
        R_Bat->breath_time = 0;
        if(++R_Bat->breath_stage > 4){
            R_Bat->breath_stage = R_Bat->vol_stage.stage;
        }
        display_data[13] = 0xF0 | (~(0xFF << R_Bat->breath_stage));
    }

    if(++R_Bat->screen_refresh_time > Refresh_Time){
        R_Bat->screen_refresh_time = 0;
        Digit_turn(&display_R.vol_bat , (R_Bat->voltage / 10));
        #if (SHOW_CURRENT_MODE == SHOW_REALTIME_CURRENT)
            Digit_turn(&display_R.cur_bat , (R_Bat->current / 10));
        #elif (SHOW_CURRENT_MODE == SHOW_SET_CURRENT)
            Digit_turn(&display_R.cur_bat , (R_Bat->current_set / 10));
        #endif
        Digit_turn(&display_R.cap_bat , (R_Bat->capacity / 10));
        Digit_turn(&display_R.c_time_bat , R_Bat->charge_time);

        uint8_t slow_charge = charger.flash_charger ? 0x00 : 0x80;
        uint8_t flash_charge = charger.flash_charger ? 0x80 : 0x00;

        display_data[3] = display_R.vol_bat.hundreds | slow_charge;
        display_data[4] = display_R.vol_bat.tens     | 0x80;
        display_data[5] = display_R.vol_bat.ones     | 0x80;

        display_data[9] = display_R.cur_bat.hundreds | flash_charge;
        display_data[10] = display_R.cur_bat.tens     | 0x80;
        display_data[11] = display_R.cur_bat.ones     | 0x80;
    }
}


void Battery_R_SET_CURRENT_func(void){
    Battery_t * R_Bat = &charger.battery_R;

    uint8_t slow_charge = charger.flash_charger ? 0x00 : 0x80;
    uint8_t flash_charge = charger.flash_charger ? 0x80 : 0x00;

    R_Bat->screen_refresh_time++;
    if(R_Bat->screen_refresh_time < ON_TIME){ 
        Digit_turn(&display_R.vol_bat , (R_Bat->voltage / 10));
        Digit_turn(&display_R.cur_bat , (R_Bat->current_set / 10));
        Digit_turn(&display_R.cap_bat , (R_Bat->capacity / 10));
        Digit_turn(&display_R.c_time_bat , R_Bat->charge_time);

        display_data[3] = display_R.vol_bat.hundreds | slow_charge;
        display_data[4] = display_R.vol_bat.tens     | 0x80;
        display_data[5] = display_R.vol_bat.ones     | 0x80;

        display_data[9] = display_R.cur_bat.hundreds | flash_charge;
        display_data[10] = display_R.cur_bat.tens     | 0x80;
        display_data[11] = display_R.cur_bat.ones     | 0x80;
    }
    else if(R_Bat->screen_refresh_time < OFF_TIME){
        display_clear_one(&display_R.cur_bat);

        display_data[3] = display_R.vol_bat.hundreds | slow_charge;
        display_data[4] = display_R.vol_bat.tens     | 0x80;
        display_data[5] = display_R.vol_bat.ones     | 0x80;

        display_data[9] = display_R.cur_bat.hundreds | flash_charge;
        display_data[10] = display_R.cur_bat.tens;
        display_data[11] = display_R.cur_bat.ones;
    }
    else{
        R_Bat->screen_refresh_time = 0;
    }

    display_data[13] = 0xF0 | (~(0xFF << R_Bat->vol_stage.stage));
}


void Battery_R_ERROR_PAGE_func(void){
    Battery_t * R_Bat = &charger.battery_R;

    R_Bat->screen_refresh_time++;
    if(R_Bat->screen_refresh_time < ON_TIME){ 
        display_clear_one(&display_R.vol_bat);
        display_show_error(&display_R , R_Bat);
    }
    else if(R_Bat->screen_refresh_time < OFF_TIME){
        display_clear_one(&display_R.cur_bat);
        display_clear_one(&display_R.vol_bat);
    }
    else{
        R_Bat->screen_refresh_time = 0;
    }
    
    uint8_t slow_charge = charger.flash_charger ? 0x00 : 0x80;
    uint8_t flash_charge = charger.flash_charger ? 0x80 : 0x00;

    display_data[3] = display_R.vol_bat.hundreds | slow_charge;
    display_data[4] = display_R.vol_bat.tens     ;//| 0x80;
    display_data[5] = display_R.vol_bat.ones     ;//| 0x80;

    display_data[9] = display_R.cur_bat.hundreds | flash_charge;
    display_data[10] = display_R.cur_bat.tens     ;//| 0x80;
    display_data[11] = display_R.cur_bat.ones     ;//| 0x80;

    display_data[13] = 0xF0 | (~(0xFF << 0));
}


/*充电结束*/
void Battery_R_CHARGE_EN_PAGE_func(void){
    Battery_t * R_Bat = &charger.battery_R;

    if(++R_Bat->screen_refresh_time > Refresh_Time){
        R_Bat->screen_refresh_time = 0;
        Digit_turn(&display_R.vol_bat , (R_Bat->voltage / 10));
        Digit_turn(&display_R.cur_bat , 0);

        Digit_turn(&display_R.cap_bat , (R_Bat->capacity / 10));
        Digit_turn(&display_R.c_time_bat , R_Bat->charge_time);

        uint8_t slow_charge = charger.flash_charger ? 0x00 : 0x80;
        uint8_t flash_charge = charger.flash_charger ? 0x80 : 0x00;

        display_data[3] = display_R.vol_bat.hundreds | slow_charge;
        display_data[4] = display_R.vol_bat.tens     | 0x80;
        display_data[5] = display_R.vol_bat.ones     | 0x80;

        display_data[9] = display_R.cur_bat.hundreds | flash_charge;
        display_data[10] = display_R.cur_bat.tens     | 0x80;
        display_data[11] = display_R.cur_bat.ones     | 0x80;

        display_data[13] = 0xF0 | (~(0xFF << R_Bat->vol_stage.stage));
    }
}





/**
 * @description: 显示对应页面
 * @param {display_Type *} pDisplay
 * @return {*}
 */
void Page_display(display_Type * pDisplay){
    pDisplay->display_func[pDisplay->page]();
}

/**
 * @description: 页面切换
 * @return {*}
 */
void Page_Change(Battery_t *pBat , display_Type * pDis){
    switch(pBat->state){
        case BAT_IDLE:
            // Reset_flash_time(pDis);
            bat_Reset_flash_time(pBat);
            pDis->page = IDLE_PAGE;
            break;

        case BAT_WAIT_ACTIVAT:
        case BAT_PreChage:
            pDis->page = CHARGE_PAGE;
            break;

        case BAT_FULL:
        case BAT_Charge_off:
            pDis->page = CHARGE_END;
            break;
        
        case BAT_Charge:
            if(pDis->page == IDLE_PAGE){
                // Reset_flash_time(pDis);
                bat_Reset_flash_time(pBat);
                pDis->page = CHARGE_PAGE;
            }
            else if(pDis->page == CHARGE_PAGE){
                if(pBat->page_SetOrEnd){
                    pBat->page_SetOrEnd = 0;
                    // Reset_flash_time(pDis);
                    bat_Reset_flash_time(pBat);
                    pDis->page = SET_CURRENT_PAGE;
                }
            }
            else if(pDis->page == SET_CURRENT_PAGE){
                if(pBat->page_SetOrEnd){
                    pBat->page_SetOrEnd = 0;
                    pBat->fast_show = 1;
                    // Reset_flash_time(pDis);
                    bat_Reset_flash_time(pBat);
                    pDis->page = CHARGE_PAGE;
                }
            }
            break;
        case BAT_Fault:
            pDis->page = ERROR_PAGE;
            break;
        default:
            break;
    }
}



/**
 * @description: 页面显示进程
 * @return {*}
 */
void Page_disp_process(void){
    Page_Change(&charger.battery_L , &display_L_page);
    Page_Change(&charger.battery_R , &display_R_page);

    Page_display(&display_L_page);
    Page_display(&display_R_page);

    AIP1640_display(display_data);
}










